package org.swim.web.servlet;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Set;

import javax.naming.NamingException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import net.sf.json.JSONObject;

import org.swim.remote.entities.ICollaboration;
import org.swim.remote.entities.ICollaboration.Status;
import org.swim.remote.entities.ICollaboration.Visibility;
import org.swim.remote.entities.IFeedback;
import org.swim.remote.entities.IMessage;
import org.swim.remote.entities.INotification;
import org.swim.remote.entities.INotification.NotificationStatus;
import org.swim.remote.entities.IUser;
import org.swim.remote.exceptions.SwimException;
import org.swim.remote.exceptions.SwimException.Severity;
import org.swim.remote.exceptions.TokenException;
import org.swim.web.servlet.consts.Action;
import org.swim.web.utils.SwimConst;
import org.swim.web.utils.SwimUtils;

public class CollaborationSL extends SwimServlet {

	private static final long serialVersionUID = 1L;

	private static final int NUM_UNDERLINED_COLLABORATION = 1;

	@Override
	protected void doRequest(HttpServletRequest request,
			HttpServletResponse response, Method method, Action action)
			throws ServletException, IOException {
		switch (action) {
		case NEWCOLLABORATION:
			// TODO Fede: CREATE NEW COLLABORATION
			try {
				createNewCollaboration(request, response);
			} catch (SwimException e) {
				e.printStackTrace();
				// TODO Fede: redirect to search or to user profile...
				try {
					Integer userId = Integer.parseInt(request
							.getParameter("userId"));
					catchSwimExcpetion(action, e, "profile?a="+Action.VIEWPROFILE+"who=" + userId,
							request, response);
				} catch (NumberFormatException e1) {
					catchGenericExcpetion(action, e, request, response);
				}
			} catch (NamingException e) {
				catchGenericExcpetion(action, e, request, response);
			}

			break;
		case VIEWCOLLABORATION:
			// TODO Fede: VIEW COLLABORATION
			try {
				viewCollaboration(request, response);
			} catch (SwimException e) {
				catchSwimExcpetion(action, e, "/", request, response);
			}
			break;
		case SENDMESSAGE:
			// TODO Fede: SENDMESSAGE
			try {
				sendMessage(request, response);
			} catch (TokenException e2) {
				e2.printStackTrace();
			} catch (SwimException e2) {
				// TODO Auto-generated catch block
				e2.printStackTrace();
			} catch (NamingException e2) {
				// TODO Auto-generated catch block
				e2.printStackTrace();
			}
			break;
		case VIEWLASTMESSAGE:
			try {
				viewLastMessage(request, response);
			} catch (NumberFormatException e2) {
				// TODO Auto-generated catch block
				e2.printStackTrace();
			} catch (SwimException e2) {
				// TODO Auto-generated catch block
				e2.printStackTrace();
			}
			break;
		case SENDFEEDBACK:
			// TODO Fede: SEND FEEDBACK
			try {
				sendFeedback(request, response);
			} catch (TokenException e2) {
				e2.printStackTrace();
				catchSwimExcpetion(action, e2, "/collaboration?a="+Action.DEFAULT, request,
						response);
			} catch (SwimException e2) {
				catchSwimExcpetion(action, e2, "/collaboration?a="+Action.DEFAULT, request,
						response);
			} catch (NamingException e2) {
				catchGenericExcpetion(action, e2, request, response);
			}
			break;
		case COMPLETECOLLABORATION:
			// TODO Fede: ACCEPT COLLABORATION
			try {
				completeCollaboration(request, response);
			} catch (SwimException e1) {
				catchSwimExcpetion(action, e1, "/collaboration?a="+Action.DEFAULT, request,
						response);
			}
			break;
		case ACCEPTCOLLABORATION:
			// TODO Fede: ACCEPT COLLABORATION
			try {
				acceptCollaboration(request, response);
			} catch (SwimException e1) {
				catchSwimExcpetion(action, e1, "/collaboration?a="+Action.DEFAULT, request,
						response);
			}
			break;
		case REJECTCOLLABORATION:
			// TODO Fede: REJECT COLLABORATION
			try {
				rejectCollaboration(request, response);
			} catch (SwimException e1) {
				catchSwimExcpetion(action, e1, "/collaboration?a="+Action.DEFAULT, request,
						response);
			}
			break;

		case VIEWALLCOLLABORATION:
		default:
			// TODO Fede: VIEW ALL COLLABORATION
			try {
				viewAllCollaboration(request, response);
			} catch (SwimException e) {
				e.printStackTrace();
				catchSwimExcpetion(action, e, "/", request, response);
			}
			break;
		}

	}

	private void sendFeedback(HttpServletRequest request,
			HttpServletResponse response) throws TokenException, SwimException,
			NamingException, IOException {
		JSONObject object = new JSONObject();
		object.accumulate("token", getToken(request));

		JSONObject feedback = new JSONObject();
		feedback.accumulate("collaborationId",
				request.getParameter("collaborationId"));
		feedback.accumulate("comment", request.getParameter("comment"));
		feedback.accumulate("valuation", request.getParameter("valuation"));

		object.accumulate("feedback", feedback);

		ICollaboration col = getCmr().postFeedback(object);

		response.sendRedirect(SwimConst.Url.Servlet.COLLABORATION + "?a="
				+ Action.VIEWCOLLABORATION + "&id=" + col.getId());

	}

	private void completeCollaboration(HttpServletRequest request,
			HttpServletResponse response) throws SwimException, IOException {
		setStatusCollaboration(request, response, Status.COMPLETED);
	}

	private void viewLastMessage(HttpServletRequest request,
			HttpServletResponse response) throws NumberFormatException,
			SwimException, ServletException, IOException {
		List<IMessage> lastMessages = new ArrayList<IMessage>();
		if (request.getParameterMap().containsKey("collaborationId")
				&& request.getParameterMap().containsKey("lastMessageTS")) {

			ICollaboration col = getCmr().get(
					Integer.parseInt(request.getParameter("collaborationId")));

			Date lastMessage = new Date(Long.parseLong(request
					.getParameter("lastMessageTS")));

			lastMessages = getLastMessages(col.getMessagesList(), lastMessage);
		}

		JSONObject otherObject;
		List<IMessage> mexs = lastMessages;
		IUser owner = getUmr().getTokenOwner(getToken(request));
		for (IMessage iMessage : mexs) {
			if (((INotification) iMessage).getNotificationStatus() == NotificationStatus.UNREAD) {
				if (iMessage.getIUserByReceiverId().equals(owner)) {
					otherObject = new JSONObject();
					otherObject.accumulate("token", getToken(request));
					otherObject.accumulate("id", iMessage.getId());
					otherObject.accumulate("status",
							INotification.NotificationStatus.READ.name());
					getCmr().setStatusMessageNotification(otherObject);
				}
			}
		}

		request.setAttribute("messages", lastMessages);
		request.getRequestDispatcher("message-list-item.jsp").forward(request,
				response);

	}

	private void sendMessage(HttpServletRequest request,
			HttpServletResponse response) throws TokenException, SwimException,
			NamingException, ServletException, IOException {

		List<IMessage> lastMessages = new ArrayList<IMessage>();
		if (request.getParameterMap().containsKey("message")
				&& request.getParameterMap().containsKey("collaborationId")
				&& request.getParameterMap().containsKey("lastMessageTS")) {

			JSONObject object = new JSONObject();
			object.accumulate("token", getToken(request));
			JSONObject message = new JSONObject();
			message.accumulate("message", request.getParameter("message"));
			message.accumulate("collaborationId",
					Integer.parseInt(request.getParameter("collaborationId")));

			object.accumulate("message", message);

			ICollaboration col = getCmr().postMessage(object);

			Date lastMessage = new Date(Long.parseLong(request
					.getParameter("lastMessageTS")));

			lastMessages = getLastMessages(col.getMessagesList(), lastMessage);
		}

		request.setAttribute("messages", lastMessages);
		request.getRequestDispatcher("message-list-item.jsp").forward(request,
				response);

	}

	private List<IMessage> getLastMessages(List<IMessage> allMessages,
			Date lastMessageTS) {
		List<IMessage> lastMessages = new ArrayList<IMessage>();

		for (IMessage iMessage : allMessages) {
			if (iMessage.getTimestamp().after(lastMessageTS)) {
				lastMessages.add(iMessage);
				System.out.println(">>>>>>>>>>>>idMex: "
						+ iMessage.getId()
						+ " ---->"
						+ SwimUtils.formatDate(iMessage.getTimestamp(),
								"dd/MM/yyyy, HH:mm"));
			}

		}
		return lastMessages;
	}

	private void rejectCollaboration(HttpServletRequest request,
			HttpServletResponse response) throws SwimException, IOException {
		setStatusCollaboration(request, response, Status.REJECTED);
	}

	private void acceptCollaboration(HttpServletRequest request,
			HttpServletResponse response) throws SwimException, IOException {
		setStatusCollaboration(request, response, Status.CONFIRMED);

	}

	private void setStatusCollaboration(HttpServletRequest request,
			HttpServletResponse response, ICollaboration.Status status)
			throws SwimException, IOException {
		JSONObject object = new JSONObject();
		object.accumulate("token", getToken(request));

		Integer collaborationId = Integer.parseInt(request
				.getParameter("collaborationId"));

		object.accumulate("collaborationId", collaborationId);
		object.accumulate("status", status.name());

		ICollaboration col = getCmr().setStatusCollaboration(object);

		JSONObject otherObject = new JSONObject();

		List<IMessage> mexs = col.getMessagesList();
		for (IMessage iMessage : mexs) {
			if (((INotification) iMessage).getNotificationStatus() == NotificationStatus.UNREAD) {
				otherObject = new JSONObject();
				otherObject.accumulate("token", getToken(request));
				otherObject.accumulate("id", iMessage.getId());
				otherObject.accumulate("status",
						INotification.NotificationStatus.READ.name());
				getCmr().setStatusMessageNotification(otherObject);
			}
		}

		if (status == Status.CONFIRMED || status == Status.COMPLETED)
			response.sendRedirect(SwimConst.Url.Servlet.COLLABORATION
					+ "?a=viewcollaboration&id=" + collaborationId);
		else
			response.sendRedirect(SwimConst.Url.Servlet.COLLABORATION);

	}

	private void viewAllCollaboration(HttpServletRequest request,
			HttpServletResponse response) throws SwimException,
			ServletException, IOException {
		JSONObject object = new JSONObject();
		object.accumulate("token", getToken(request));
		List<ICollaboration> myCollaborations = getCmr().getMyCollaborations(
				object);

		Integer lastColIndex = myCollaborations.size() > NUM_UNDERLINED_COLLABORATION ? NUM_UNDERLINED_COLLABORATION
				: myCollaborations.size();
		List<ICollaboration> lastColls = myCollaborations.subList(0,
				lastColIndex);
		List<ICollaboration> otherColls;
		if (lastColIndex < NUM_UNDERLINED_COLLABORATION)
			otherColls = new ArrayList<ICollaboration>();
		else
			otherColls = myCollaborations.subList(lastColIndex,
					myCollaborations.size());

		request.setAttribute("lastColls", lastColls);
		request.setAttribute("otherColls", otherColls);

		if(lastColls.size() +  otherColls.size() > 0)
		request.getRequestDispatcher("collaborations.jsp").forward(request,
				response);
		else
			response.sendRedirect(SwimConst.Url.Servlet.PROFILE);

	}

	private void createNewCollaboration(HttpServletRequest request,
			HttpServletResponse response) throws SwimException,
			NamingException, IOException, ServletException {
		String titleCollaboration = request.getParameter("title");
		String message = request.getParameter("message");
		Integer userId = Integer.parseInt(request.getParameter("userId"));
		String email = request.getParameter("email");
		String senderVis = request.getParameter("senderVisibility");
		Visibility senderVisibility;
		if (senderVis != null)
			senderVisibility = Visibility.valueOf(senderVis.toUpperCase());
		else
			senderVisibility = Visibility.HIDDEN;

		JSONObject object = new JSONObject();
		JSONObject collaborationJson = new JSONObject();
		JSONObject messageJson = new JSONObject();

		collaborationJson.accumulate("title", titleCollaboration);
		collaborationJson.accumulate("receiverId", userId);
		collaborationJson.accumulate("senderVisibility",
				senderVisibility.name());

		messageJson.accumulate("message", message);

		object.accumulate("collaboration", collaborationJson);
		object.accumulate("message", messageJson);

		ICollaboration collaboration;
		if (!SwimUtils.isLogged(request)) {
			object.accumulate("senderEmail", email);
			collaboration = getCmr().createBaseCollaboration(object);
		} else {
			String token = getToken(request);
			object.accumulate("token", token);
			collaboration = getCmr().createCollaboration(object);
		}

		viewCollaboration(request, response, collaboration);
	}

	private void viewCollaboration(HttpServletRequest request,
			HttpServletResponse response, ICollaboration collaboration)
			throws IOException, ServletException, SwimException {
		List<ICollaboration> myCols = new ArrayList<ICollaboration>();
		request.setAttribute("collaboration", collaboration);

		if (SwimUtils.isLogged(request)) {
			JSONObject object = new JSONObject();
			object.accumulate("token", getToken(request));
			myCols = getCmr().getMyCollaborations(object);

			JSONObject otherObject;
			List<IMessage> mexs = collaboration.getMessagesList();
			IUser owner = getUmr().getTokenOwner(getToken(request));
			for (IMessage iMessage : mexs) {
				if (((INotification) iMessage).getNotificationStatus() == NotificationStatus.UNREAD) {
					if (iMessage.getIUserByReceiverId().equals(owner)) {
						otherObject = new JSONObject();
						otherObject.accumulate("token", getToken(request));
						otherObject.accumulate("id", iMessage.getId());
						otherObject.accumulate("status",
								INotification.NotificationStatus.READ.name());
						getCmr().setStatusMessageNotification(otherObject);
					}
				}
			}

			Set<IFeedback> feedbacks = collaboration.getFeedbacksSet();
			for (IFeedback iFeedback : feedbacks) {
				if (iFeedback.getIUserByReceiverId().equals(owner)) {
					otherObject = new JSONObject();
					otherObject.accumulate("token", getToken(request));
					otherObject.accumulate("id", iFeedback.getId());
					otherObject.accumulate("status",
							INotification.NotificationStatus.READ.name());
					getCmr().setStatusFeedbackNotification(otherObject);
				}
			}
			
			reloadNotification(request);
		}

		request.setAttribute("myCols", myCols);

		request.getRequestDispatcher("collaboration.jsp").forward(request,
				response);

	}

	private void viewCollaboration(HttpServletRequest request,
			HttpServletResponse response) throws SwimException, IOException,
			ServletException {
		try {
			Integer collaborationId = Integer.parseInt(request
					.getParameter("id"));
			ICollaboration collaboration = getCmr().get(collaborationId);
			viewCollaboration(request, response, collaboration);

		} catch (NumberFormatException e) {
			throw new SwimException("No collaboration selected!",
					Severity.ERROR);
		}

	}
}
